package actions;

import flixel.FlxSprite;
import flixel.FlxObject;
import flixel.tweens.FlxTween;
import flixel.group.FlxTypedGroup;
import flixel.util.FlxPoint;
import flixel.group.FlxSpriteGroup;
import flixel.FlxG;
import flixel.tweens.FlxTween;
import actions.ExecutableAction;
import actions.BasicAction;
import actions.BasicContainer;
import actions.Defs;
import utils.Frame;

class ActionSource extends FlxObject{
	private var _availableActions: Map<String, Int>;
	private var _actions: FlxTypedGroup<BasicAction>;
	public var alphaMultiplier: Float = 1;
	private var _window: Frame;
	public var alpha(get, set): Float;

	public function new(X: Float, Y: Float, availableActionsStr: String)
	{
		super(X, Y);
		alpha = 1;
		_window = new Frame(this, "assets/img/frame2");
		_actions = new FlxTypedGroup<BasicAction>();

		_availableActions = new Map<String, Int>();

		// parsea la cadena con acciones disponibles y crea los "slots"
		availableActionsStr = availableActionsStr.toUpperCase();
		availableActionsStr = StringTools.replace(availableActionsStr, " ", "");
		
		for( i in 0...availableActionsStr.length )
		{
			var type = availableActionsStr.charAt(i);
			
			if(_availableActions.exists(type))
			{
				_availableActions[type] = _availableActions[type] + 1;
			}
			else
			{
				_availableActions[type] = 1;
			}
		}

		for(i in _availableActions.keys()){
			_actions.add(new ExecutableAction(0, 0, i));
		}
		reorderAndResize();
		_window.update();
		setSlotsAlpha();
	}

	//////////////////////////////////////////////////
	///	Devuelve el tipo de acción que hay en una posición, o null
	//////////////////////////////////////////////////
	public function pick(position: FlxPoint): BasicAction{
		var count: Int = 0;
		for(i in _actions)
		{
			if(i.overlapsPoint(position))
			{
				
				if(_availableActions[i.actionType] > 0)
				{
					_availableActions[i.actionType] = _availableActions[i.actionType] - 1;
					setSlotsAlpha();
					return new ExecutableAction(position.x, position.y, i.actionType);
				}
				else
				{
					return null;
				}
				
				
			}



			count = count + 1;
		}
		return null;
	}

	//////////////////////////////////////////////////
	///	Posiciona las acciones y actualiza el tamaño del contenedor
	/// Es llamado por unica vez al principio, luego de cargar las acciones
	//////////////////////////////////////////////////
	private function reorderAndResize()
	{
		var accumHeight: Float = Defs.CONTAINER_VPADDING;
		var w: Float = 0;
		for(a in _actions)
		{
			w = a.width;
			a.x = x + Defs.CONTAINER_HPADDING;
			a.y = y + accumHeight;
			accumHeight += a.height + Defs.CONTAINER_VPADDING;

		}
		width = w + Defs.CONTAINER_HPADDING * 2;
		height = accumHeight;
	}



	//////////////////////////////////////////////////
	///	Devuelve la posición del slot para un determinado tipo de acción
	//////////////////////////////////////////////////
	public function getActionSlotPosition(actionType: BasicAction): FlxPoint
	{
		for(a in _actions)
		{
			if(a.actionType == actionType.actionType)
			{
				return new FlxPoint(a.x, a.y);
			}
		}
		throw "ERROR: ActionSource::getActionSlotPosition(): El tipo no existe.";
	}

	public override function draw()
	{
		_window.draw();
		_actions.draw();
		if(_droppedAction != null)
		{
			_droppedAction.draw();
		}
	}


	public function set_alpha(Alpha: Float): Float
	{
		if(_window != null)
			_window.alpha = Alpha * alphaMultiplier;

		if(_actions != null)
		{
			for(a in _actions)
			{
				a.alpha = Alpha * alphaMultiplier;
			}
		}
		return Alpha;
	}

	public function get_alpha(): Float
	{
		return _window.alpha;
	}

	//////////////////////////////////////////////////
	/// Lanza el tween al soltar la acción arrastrada
	//////////////////////////////////////////////////
	public function drop(DroppedAction: BasicAction)
	{
		if(_droppedAction == null)
		{
			_droppedAction = DroppedAction;
			var options:TweenOptions = { type: FlxTween.ONESHOT, ease: Defs.TWEEN_EASING, complete: onDropEnd}
			var aux: FlxPoint = getActionSlotPosition(_droppedAction);
			_dropTween = FlxTween.tween(_droppedAction, {x: aux.x, y: aux.y, alpha: 0.2}, 0.2, options);
		}


	}

	private function onDropEnd(Tween: FlxTween)
	{
		_availableActions[_droppedAction.actionType] = _availableActions[_droppedAction.actionType] + 1;
		_dropTween = null;
		_droppedAction = null;
		setSlotsAlpha();

	}

	private function setSlotsAlpha()
	{
		// este codigo está repetido por el return de arriba
		for(i in _actions)
		{
			if(_availableActions[i.actionType]>0)
			{
				i.alpha = 1 * alphaMultiplier;
			}
			else
			{
				i.alpha = 0.5 * alphaMultiplier;
			}
		}
	}

	private var _dropTween: FlxTween = null;				// tween utilizado soltar la acción arrastrada
	private var _droppedAction: BasicAction = null;
}